package com.itheima.relfect;


import com.itheima.domain.Person;

/**
 * 反射  框架设计的灵魂
 *      框架：半成品软件  开发人员在框架的基础上进行开发   简化编码
 *      写框架源代码的时候用到了反射
 *
 * 反射：将类的各个组成部分封装为对象 这就是反射机制
 *      Java 代码在计算机中经理的三个阶段
 *          -- 源代码阶段(Source)：
 *              首先新建一个 Java 文件 在里面编写一个类 有成员变量 成员方法 构造方法
 *              这个源代码文件可以被编译成一个字节码文件 这个字节码文件有三个部分 分别封装成员变量 成员方法 构造方法
 *              所以现在这两个 .java .class 文件 并且都在硬盘上存着的阶段(没有进内存) 的阶段叫源代码阶段
 *          -- 类对象阶段( Class )：  --> 所有对象 的创建都是通过这个类对象来创建对象
 *              这个阶段是个中间阶段 把字节码文件 .class 加载进内存 用 类加载器 ( ClassLoader )
 *              在内存中怎么描述你加载进去的这个字节码文件 ？？？  --> 对象：Class 类对象 用来描述所有字节码文件的特征的文件
 *              封装了所有字节码我呢见的共同属性：这三个都是数组 封装了所有字节码文件的共有属性
 *                  -- 成员变量 Field []
 *                  -- 成员方法 Method []
 *                  -- 构造方法 Constructor []
 *          -- 运行时阶段(Runtime)：
 *              当你用 new Person 这样构造对象的时候
 * 可见反射机制关键是要获得 CLass 阶段的 Class 对象中的三个数组 因为他们封装了所有类的成员变量 成员方法 构造方法等属性
 * 好处：可以在程序运行中操作这些对象
 *      比如代码提示：当你写代码的时候 IDEA 会自动 javac 并且将字节码文件加载进内存 然后获得这三个数组 从而知道了这个类有哪些方法 然后回显出来给你提示
 *
 * 获取 CLass 类对象的三个方式：
 *      -- 第一个阶段(没加载进内存)： Class.forName(对象的全类名) 手动将字节码文件加载进内存
 *      -- 第二个阶段(已经加载进内存)： 类名.class
 *      -- 第三个阶段(已经加载进内存)： 对象.getClass()    这个是封装在 Object 对象里的方法
 *
 * 对象字节码在内存中只有一份 怎么获取都是同一个
 *
 * Class 对象的功能：
 *    -- 获取成员变量们
 *          getFields()     获取所有 public 修饰的     .setAccessible(true)    暴力反射
 *          getField(String name)
 *          getDeclaredFields()
 *          getDeclaredField(String name)
 *    -- 获取成员方法们
 *          getMethods()    .invoke 执行方法
 *          getMethod(String name,Class... args)
 *          getDeclaredMethods()
 *          getDeclaredMethod(String name , Class... args)
 *    -- 获取构造方法们
 *          getConstructors()   .newInstance() 创建对象
 *          getConstructor(String name , Class... args)
 *          getDeclaredConstructors()
 *          getDeclaredConstructor(String name , Class... args)
 *    -- 获取类名
 */
public class ReflectDemo1 {

    public static void main(String [] args) throws ClassNotFoundException {
        //第一种方式
        Class aClass = Class.forName("com.itheima.domain.Person");
        System.out.println(aClass);
        //第二种方式
        Class<Person> personClass = Person.class;
        System.out.println(personClass);
        //第三种方式
        Person person = new Person();
        Class aClass1 = person.getClass();

        System.out.println(aClass1 == aClass && aClass == personClass);
    }
}
